/*
 * @Description  :
 * @Version      :
 * @Company      :
 * @Author       :
 * @Date         :
 * @LastEditTime : 2023-02-04 17:04:32
 */
#include "TFT_ST7735.h"

#ifdef SIMPLE

TFT_ST7735 tft(TFT_BL, TFT_DC, TFT_CS, TFT_WIDTH, TFT_HEIGHT, TFT_ST7735::ROTATION_RIGHT);

extern "C" void spiInit(void);
extern "C" void spiDataSizeSet(uint32_t dataSize);

TFT_ST7735::TFT_ST7735(int32_t pwrPin, int32_t dcPin, int32_t csPin, uint16_t width, uint16_t height, uint8_t rotation)
{
	this->pwrPin = pwrPin;
	this->dcPin = dcPin;
	this->csPin = csPin;

	this->width = width;
	this->height = height;

	this->rotation = rotation;
}

TFT_ST7735::~TFT_ST7735()
{
}

void TFT_ST7735::backlightOn(void)
{
	digitalWrite(this->pwrPin, LOW); // 背光P-MOS反逻辑
}

void TFT_ST7735::backlightOff(void)
{
	digitalWrite(this->pwrPin, HIGH);
}

void TFT_ST7735::init(void)
{
	digitalWrite(this->pwrPin, LOW);
	pinMode(this->pwrPin, OUTPUT);
	digitalWrite(this->pwrPin, LOW);

	pinMode(this->dcPin, OUTPUT);
	digitalWrite(this->dcPin, HIGH);
	pinMode(this->csPin, OUTPUT);
	digitalWrite(csPin, HIGH);

	/* SPI2 硬件初始化 */
	spiInit();

	/* 开始ST7789的初始化 */
	this->startWrite();
	this->writeCommand(0x11); // Sleep out
	delay(50);
	this->writeCommand(0x36);
	switch (this->rotation)
	{
	case ROTATION_DOWN:
	{
		this->writeByte(0x08);
	}
	break;

	case ROTATION_LEFT:
	{
		this->writeByte(0xC8);
	}
	break;

	case ROTATION_UP:
	{
		this->writeByte(0x78);
	}
	break;
	case ROTATION_RIGHT:
	{
		this->writeByte(0xA8);
	}
	break;

	default:
		break;
	}

	this->writeCommand(0xB1); // Normal mode
	this->writeByte(0x05);
	this->writeByte(0x3C);
	this->writeByte(0x3C);
	this->writeCommand(0xB2); // Idle mode
	this->writeByte(0x05);
	this->writeByte(0x3C);
	this->writeByte(0x3C);
	this->writeCommand(0xB3); // Partial mode
	this->writeByte(0x05);
	this->writeByte(0x3C);
	this->writeByte(0x3C);
	this->writeByte(0x05);
	this->writeByte(0x3C);
	this->writeByte(0x3C);
	this->writeCommand(0xB4); // Dot inversion
	this->writeByte(0x03);
	this->writeCommand(0xC0); // AVDD GVDD
	this->writeByte(0xAB);
	this->writeByte(0x0B);
	this->writeByte(0x04);
	this->writeCommand(0xC1); // VGH VGL
	this->writeByte(0xC5);	  // C0
	this->writeCommand(0xC2); // Normal Mode
	this->writeByte(0x0D);
	this->writeByte(0x00);
	this->writeCommand(0xC3); // Idle
	this->writeByte(0x8D);
	this->writeByte(0x6A);
	this->writeCommand(0xC4); // Partial+Full
	this->writeByte(0x8D);
	this->writeByte(0xEE);
	this->writeCommand(0xC5); // VCOM
	this->writeByte(0x0F);
	this->writeCommand(0xE0); // positive gamma
	this->writeByte(0x07);
	this->writeByte(0x0E);
	this->writeByte(0x08);
	this->writeByte(0x07);
	this->writeByte(0x10);
	this->writeByte(0x07);
	this->writeByte(0x02);
	this->writeByte(0x07);
	this->writeByte(0x09);
	this->writeByte(0x0F);
	this->writeByte(0x25);
	this->writeByte(0x36);
	this->writeByte(0x00);
	this->writeByte(0x08);
	this->writeByte(0x04);
	this->writeByte(0x10);
	this->writeCommand(0xE1); // negative gamma
	this->writeByte(0x0A);
	this->writeByte(0x0D);
	this->writeByte(0x08);
	this->writeByte(0x07);
	this->writeByte(0x0F);
	this->writeByte(0x07);
	this->writeByte(0x02);
	this->writeByte(0x07);
	this->writeByte(0x09);
	this->writeByte(0x0F);
	this->writeByte(0x25);
	this->writeByte(0x35);
	this->writeByte(0x00);
	this->writeByte(0x09);
	this->writeByte(0x04);
	this->writeByte(0x10);
	this->writeCommand(0xFC);
	this->writeByte(0x80);
	this->writeCommand(0x3A);
	this->writeByte(0x05);
	this->writeCommand(0x21); // Display inversion
	this->writeCommand(0x29); // Display on
	this->writeCommand(0x2A); // Set Column Address
	this->writeByte(0x00);
	this->writeByte(0x1A); // 26
	this->writeByte(0x00);
	this->writeByte(0x69);	  // 105
	this->writeCommand(0x2B); // Set Page Address
	this->writeByte(0x00);
	this->writeByte(0x01); // 1
	this->writeByte(0x00);
	this->writeByte(0xA0); // 160
	this->writeCommand(0x2C);

	this->endWrite();
}

void TFT_ST7735::enterSleepMode()
{
	this->writeCommand(0x10); // Sleep in
	this->backlightOff();
}

void TFT_ST7735::fillScreen(uint16_t color)
{
	uint16_t colorBuffer[TFT_WIDTH];

	for (uint16_t width = 0; width < this->width; width++)
	{
		colorBuffer[width] = color;
	}

	this->startWrite();
	for (uint16_t height = 0; height < this->height; height++)
	{
		if (this->setAddrWindow(0, height, this->width, 1))
		{
			this->writePixels(colorBuffer, this->width);
		}
	}
	this->endWrite();
}

void TFT_ST7735::startWrite(void)
{
	digitalWrite(this->csPin, LOW);
}

bool TFT_ST7735::setAddrWindow(uint16_t xs, uint16_t ys, uint16_t width, uint16_t height)
{
	uint16_t xe = xs + width - 1;
	uint16_t ye = ys + height - 1;

	if ((xs > this->width) || (xe > this->width))
		return false;

	if ((ys > this->height) || (ye > this->height))
		return false;

	switch (this->rotation)
	{
	case ROTATION_DOWN:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(xs + 26);
		writeWord(xe + 26);
		writeCommand(0x2B); //行地址设置
		writeWord(ys + 1);
		writeWord(ye + 1);
	}
	break;

	case ROTATION_LEFT:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(xs + 26);
		writeWord(xe + 26);
		writeCommand(0x2B); //行地址设置
		writeWord(ys + 1);
		writeWord(ye + 1);
	}
	break;

	case ROTATION_UP:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(xs + 1);
		writeWord(xe + 1);
		writeCommand(0x2B); //行地址设置
		writeWord(ys + 26);
		writeWord(ye + 26);
	}
	break;

	case ROTATION_RIGHT:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(xs + 1);
		writeWord(xe + 1);
		writeCommand(0x2B); //行地址设置
		writeWord(ys + 26);
		writeWord(ye + 26);
	}
	break;
	default:
		break;
	}
	writeCommand(0x2C); //储存器写

	return true;
}

void TFT_ST7735::writePixels(uint16_t *colors, uint32_t size)
{
	spiDataSizeSet(SPI_DATASIZE_16BIT);

	uint32_t colorBuffCount = 0;

	while (size / 0xFFFE) // 避免HAL_SPI_Transmit_DMA函数中的Size溢出
	{
		HAL_SPI_Transmit_DMA(&this->handleSPI2, (uint8_t *)(&colors[colorBuffCount]), 0xFFFE);
		while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&this->handleSPI2))
			;
		size -= 0xFFFE;
		colorBuffCount += 0xFFFE;
	}

	HAL_SPI_Transmit_DMA(&this->handleSPI2, (uint8_t *)(&colors[colorBuffCount]), size);
	while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&this->handleSPI2))
		;
}
void TFT_ST7735::writePixel(uint16_t x, uint16_t y, uint16_t color)
{
	uint16_t xe = x + 1;
	uint16_t ye = y + 1;

	if ((x > this->width) || (xe > this->width))
		return;

	if ((y > this->height) || (ye > this->height))
		return;

	switch (this->rotation)
	{
	case ROTATION_DOWN:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(x + 26);
		writeWord(xe + 26);
		writeCommand(0x2B); //行地址设置
		writeWord(y + 1);
		writeWord(ye + 1);
	}
	break;

	case ROTATION_LEFT:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(x + 26);
		writeWord(xe + 26);
		writeCommand(0x2B); //行地址设置
		writeWord(y + 1);
		writeWord(ye + 1);
	}
	break;

	case ROTATION_UP:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(x + 1);
		writeWord(xe + 1);
		writeCommand(0x2B); //行地址设置
		writeWord(y + 26);
		writeWord(ye + 26);
	}
	break;

	case ROTATION_RIGHT:
	{
		writeCommand(0x2A); //列地址设置
		writeWord(x + 1);
		writeWord(xe + 1);
		writeCommand(0x2B); //行地址设置
		writeWord(y + 26);
		writeWord(ye + 26);
	}
	break;
	default:
		break;
	}
	writeCommand(0x2C); //储存器写

	spiDataSizeSet(SPI_DATASIZE_16BIT);
	HAL_SPI_Transmit_DMA(&this->handleSPI2, (uint8_t *)(&color), 1);
	while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&this->handleSPI2))
		;
}

void TFT_ST7735::endWrite(void)
{
	digitalWrite(this->csPin, HIGH);
}

void TFT_ST7735::writeByte(uint8_t data)
{
	spiDataSizeSet(SPI_DATASIZE_8BIT);

	HAL_SPI_Transmit_DMA(&handleSPI2, &data, 1);
	while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&this->handleSPI2))
		; // 等待传输完成
}

void TFT_ST7735::writeWord(uint16_t data)
{
	this->writeByte((data >> 8) & 0xFF);
	this->writeByte((data >> 0) & 0xFF);
}

void TFT_ST7735::writeCommand(uint8_t cmd)
{
	digitalWrite(this->dcPin, LOW);

	this->writeByte(cmd);

	digitalWrite(this->dcPin, HIGH);
}

#ifdef __cplusplus
extern "C"
{
#endif
	void spiDataSizeSet(uint32_t dataSize)
	{
		static uint32_t lastDataSize = SPI_DATASIZE_8BIT;

		if (lastDataSize == dataSize)
			return;

		if (dataSize == SPI_DATASIZE_8BIT)
		{
			tft.handleSPI2DMATx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
			tft.handleSPI2DMATx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
			tft.handleSPI2.Init.DataSize = SPI_DATASIZE_8BIT;
		}
		else
		{
			tft.handleSPI2DMATx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
			tft.handleSPI2DMATx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
			tft.handleSPI2.Init.DataSize = SPI_DATASIZE_16BIT;
		}

		lastDataSize = dataSize;
		HAL_SPI_Init(&tft.handleSPI2);

		__HAL_DMA_DISABLE(&tft.handleSPI2DMATx); // 必须先Disable DMA才能配置
		HAL_DMA_Init(&tft.handleSPI2DMATx);
	}

	/* 此处直接默认将SPI2初始化成为SPI_MODE_3 */
	void spiInit(void)
	{
		tft.handleSPI2.Instance = SPI2;
		tft.handleSPI2.Init.Mode = SPI_MODE_MASTER;
		tft.handleSPI2.Init.Direction = SPI_DIRECTION_2LINES;
		tft.handleSPI2.Init.NSS = SPI_NSS_SOFT;
		tft.handleSPI2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
		tft.handleSPI2.Init.FirstBit = SPI_FIRSTBIT_MSB;
		tft.handleSPI2.Init.TIMode = SPI_TIMODE_DISABLE;
		tft.handleSPI2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
		tft.handleSPI2.Init.CRCPolynomial = 7;
		tft.handleSPI2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
		tft.handleSPI2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

		tft.handleSPI2.Init.DataSize = SPI_DATASIZE_8BIT;

		/* SPI_MODE_3 */
		tft.handleSPI2.Init.CLKPolarity = SPI_POLARITY_HIGH;
		tft.handleSPI2.Init.CLKPhase = SPI_PHASE_2EDGE;

		if (HAL_SPI_Init(&tft.handleSPI2) != HAL_OK)
		{
			Serial.println("TFT Hardware SPI2 init failed!");
		}
	}

	/* SPI相关硬件初始化,在HAL_SPI_Init()内部自动调用 */
	void HAL_SPI_MspInit(SPI_HandleTypeDef *spiHandle)
	{
		GPIO_InitTypeDef GPIO_InitStruct = {0};
		if (spiHandle->Instance == SPI2)
		{
			__HAL_RCC_DMA1_CLK_ENABLE();

			HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
			HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

			__HAL_RCC_SPI2_CLK_ENABLE();

			__HAL_RCC_GPIOB_CLK_ENABLE();
			/*
				PB13     ------> SPI2_SCK
				PB15     ------> SPI2_MOSI
			*/
			GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_15;
			GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
			GPIO_InitStruct.Pull = GPIO_PULLUP;
			GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
			GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
			HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

			/* SPI2 DMA Init */
			/* SPI2_TX Init */
			tft.handleSPI2DMATx.Instance = DMA1_Channel5;
			tft.handleSPI2DMATx.Init.Request = DMA_REQUEST_1;
			tft.handleSPI2DMATx.Init.Direction = DMA_MEMORY_TO_PERIPH;
			tft.handleSPI2DMATx.Init.PeriphInc = DMA_PINC_DISABLE;
			tft.handleSPI2DMATx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
			tft.handleSPI2DMATx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
			tft.handleSPI2DMATx.Init.Mode = DMA_NORMAL;
			tft.handleSPI2DMATx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

			tft.handleSPI2DMATx.Init.MemInc = DMA_MINC_ENABLE;

			if (HAL_DMA_Init(&tft.handleSPI2DMATx) != HAL_OK)
			{
				Serial.println("TFT Hardware SPI2-DMA init failed!");
			}

			__HAL_LINKDMA(&tft.handleSPI2, hdmatx, tft.handleSPI2DMATx);
		}
	}

	void HAL_SPI_MspDeInit(SPI_HandleTypeDef *spiHandle)
	{
		if (spiHandle->Instance == SPI2)
		{
			/* Peripheral clock disable */
			__HAL_RCC_SPI2_CLK_DISABLE();

			/*
				SPI2 GPIO Configuration
				PB13     ------> SPI2_SCK
				PB15     ------> SPI2_MOSI
			*/
			HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13 | GPIO_PIN_15);

			/* SPI2 DMA DeInit */
			HAL_DMA_DeInit(spiHandle->hdmatx);
		}
	}

	void DMA1_Channel5_IRQHandler(void)
	{
		HAL_DMA_IRQHandler(&tft.handleSPI2DMATx);
	}

#ifdef __cplusplus
}
#endif // __cplusplus

/*
 * function:drawLine
 * parameter: xs:x 轴起始坐标，
 *            ys:y 轴起始坐标
 *            xe:x 轴结束坐标，
 *            ye:y 轴结束坐标
 *            color: 画线的颜色
 * return：void
 */
void TFT_ST7735::drawLine(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye, uint16_t color)
{
	if ((xs == xe) || (ys == ye))
	{
		bool selectflag = (xs == xe);
		uint16_t pointCount = 0;
		uint16_t localDisplayBuff[selectflag ? TFT_HEIGHT : TFT_WIDTH] = {0};
		pointCount = selectflag ? (ye - ys + 1) : (xe - xs + 1);

		for (int i = 0; i < pointCount; i++)
		{
			localDisplayBuff[i] = color;
		}

		startWrite();
		if (setAddrWindow(xs, ys, selectflag ? 1 : pointCount, selectflag ? pointCount : 1)) // 设置光标位置与填充区域
		{
			writePixels(localDisplayBuff, pointCount);
		}
		endWrite();
	}
	else
	{
		uint16_t t;
		int xerr = 0, yerr = 0, delta_x, delta_y, distance;
		int incx, incy, uRow, uCol;
		delta_x = xe - xs + 1; //计算坐标增量
		delta_y = ye - ys + 1;
		uRow = xs; //画线起点坐标
		uCol = ys;
		if (delta_x > 0)
			incx = 1; //设置单步方向
		else if (delta_x == 0)
			incx = 0; //垂直线
		else
		{
			incx = -1;
			delta_x = -delta_x;
		}
		if (delta_y > 0)
			incy = 1;
		else if (delta_y == 0)
			incy = 0; //水平线
		else
		{
			incy = -1;
			delta_y = -delta_y;
		}
		if (delta_x > delta_y)
			distance = delta_x; //选取基本增量坐标轴
		else
			distance = delta_y;

		startWrite();
		for (t = 0; t < distance + 1; t++)
		{
			writePixel(uRow, uCol, color); //画点
			xerr += delta_x;
			yerr += delta_y;
			if (xerr > distance)
			{
				xerr -= distance;
				uRow += incx;
			}
			if (yerr > distance)
			{
				yerr -= distance;
				uCol += incy;
			}
		}
		endWrite();
	}
}

/*
 * function:drawRect
 * parameter: xs:x 轴起始坐标，
 *            ys:y 轴起始坐标
 *            xe:x 轴结束坐标，
 *            ye:y 轴结束坐标
 *            color: 画线的颜色
 * return：void
 */
void TFT_ST7735::drawRect(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye, uint16_t color)
{
	drawLine(xs, ys, xe, ys, color);
	drawLine(xs, ys, xs, ye, color);
	drawLine(xe, ys, xe, ye, color);
	drawLine(xs, ye, xe, ye, color);
}

/*
 * function:drawCircle
 * parameter: x:x 轴圆心坐标，
 *            y:y 轴圆心坐标
 *			 r： 圆的半径
 *            color: 画线的颜色
 * return：void
 */
void TFT_ST7735::drawCircle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{
	int a, b;
	a = 0;
	b = r;
	startWrite();
	while (a <= b)
	{
		writePixel(x - b, y - a, color); // 3
		writePixel(x + b, y - a, color); // 0
		writePixel(x - a, y + b, color); // 1
		writePixel(x - a, y - b, color); // 2
		writePixel(x + b, y + a, color); // 4
		writePixel(x + a, y - b, color); // 5
		writePixel(x + a, y + b, color); // 6
		writePixel(x - b, y + a, color); // 7
		a++;
		if ((a * a + b * b) > (r * r)) //判断要画的点是否过远
		{
			b--;
		}
	}
	endWrite();
}

void TFT_ST7735::fillCircle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{
	for (; r > 0; r--)
	{
		drawCircle(x, y, r, color);
	}
}
void TFT_ST7735::drawBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t bitmap[]) {}

void TFT_ST7735::fillRect(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye, uint16_t color)
{
	uint16_t colorBuffer[TFT_WIDTH];

	for (uint16_t width = xs; width < xe + 1; width++)
	{
		colorBuffer[width] = color;
	}

	this->startWrite();
	for (uint16_t height = ys; height < ye; height++)
	{
		if (this->setAddrWindow(xs, height, xe - xs + 1, 1))
		{
			this->writePixels(&colorBuffer[xs], xe - xs + 1);
		}
	}
	this->endWrite();
}

/*
 * function:drawChar
 * parameter: x:x 轴显式坐标，
 *            y:y 轴显式坐标
 *			  ch：显式的字符
 *            charColor: 字符的颜色
 * 			  backgroundColor：背景的颜色
 *            size：字号:12,16,24,32
 * return：void
 */
void TFT_ST7735::drawChar(uint16_t x, uint16_t y, const char ch,
						  uint16_t color, uint16_t bgColor, uint8_t size)
{
	uint16_t temp, sizex, t, m = 0, n = 0; // sizex为字符宽度，m记录行，n记录列
	uint16_t i, TypefaceNum;			   //一个字符所占字节大小
	uint16_t x0 = x;
	sizex = size / 2;
	TypefaceNum = (sizex / 8 + ((sizex % 8) ? 1 : 0)) * size;
	char chTemp = ch - ' '; //得到偏移后的值

	uint16_t localDisplayBuff[32 * 16] = {0}; // 先将底色绘制到内存中，最大字体为32*16
	for (int i = 0; i < size * sizex; i++)
	{
		localDisplayBuff[i] = bgColor;
	}

	for (i = 0; i < TypefaceNum; i++)
	{
		if (size == 12)
		{
			temp = ascii_1206[chTemp][i]; //调用6x12字体
		}
		else if (size == 16)
		{
			temp = ascii_WenQuanYiDengKuan_1608[chTemp][i]; //调用8x16字体
		}
		else if (size == 24)
		{
			temp = ascii_WenQuanYiDengKuan_2412[chTemp][i]; //调用12x24字体
		}
		else if (size == 32)
		{
			temp = ascii_wenquan_3216[chTemp][i]; //调用16x32字体
		}
		else
		{
			return;
		}
		for (t = 0; t < 8; t++)
		{
			if (temp & (0x01 << t))
			{
				localDisplayBuff[n * sizex + m] = color;
			}
			m++; // 记录一行中的像素点位置
			if (m % sizex == 0)
			{
				n++;   // 一行记录完成，行号加一
				m = 0; // 列号清零
				break;
			}
		}
	}
	startWrite();
	if (setAddrWindow(x, y, sizex, size)) // 设置光标位置与填充区域
	{
		writePixels(localDisplayBuff, size * sizex);
	}
	endWrite();
}

/*
 * function:drawString
 * parameter: x:x 轴显式坐标，
 *            y:y 轴显式坐标
 *			  str:要显式的字符串
 *            color: 字符的颜色
 * 			  bgColor
 *            size：字号:12,16,24,32
 * return：void
 */
void TFT_ST7735::drawString(uint16_t x, uint16_t y, const char *str,
							uint16_t color, uint16_t bgColor, uint8_t size)
{
	while (*str != '\0')
	{
		drawChar(x, y, *str, color, bgColor, size);
		x += size / 2;
		str++;
	}
}

/*
 * function:drawHanZi1212
 * parameter: x:x 轴显式坐标，
 *            y:y 轴显式坐标
 *			  hanZi:要显式中文
 *            color: 字符的颜色
 * 			  bgColor
 * return：void
 */
void TFT_ST7735::drawHanZi1212(uint16_t x, uint16_t y, const char *hanZi,
							   uint16_t color, uint16_t bgColor)
{
	uint8_t i, j, m = 0, n = 0; // m记录行，n记录列
	uint16_t k;
	uint16_t HZnum;		  //汉字数目
	uint16_t TypefaceNum; //一个字符所占字节大小
	uint16_t x0 = x;
	uint8_t size = 12;
	TypefaceNum = (size / 8 + ((size % 8) ? 1 : 0)) * size;

	uint16_t localDisplayBuff[12 * 12] = {0}; // 先将底色绘制到内存中
	for (int i = 0; i < 12 * 12; i++)
	{
		localDisplayBuff[i] = bgColor;
	}

	HZnum = sizeof(tfont12) / sizeof(typFNT_GB12); //统计汉字数目
	for (k = 0; k < HZnum; k++)
	{
		if ((tfont12[k].Index[0] == *(hanZi)) && (tfont12[k].Index[1] == *(hanZi + 1)))
		{
			for (i = 0; i < TypefaceNum; i++)
			{
				for (j = 0; j < 8; j++)
				{
					if (tfont12[k].Msk[i] & (0x01 << j))
					{
						localDisplayBuff[n * 12 + m] = color;
					}
					m++; // 记录一行中的像素点位置
					if (m % size == 0)
					{
						n++;   // 一行记录完成，行号加一
						m = 0; // 列号清零
						break;
					}
				}
			}
		}
		continue; //查找到对应点阵字库立即退出，防止多个汉字重复取模带来影响
	}

	startWrite();
	if (setAddrWindow(x, y, size, size)) // 设置光标位置与填充区域
	{
		writePixels(localDisplayBuff, size * size);
	}
	endWrite();
}

/*
 * function:drawHanZi1616
 * parameter: x:x 轴显式坐标，
 *            y:y 轴显式坐标
 *			  hanZi:要显式中文
 *            color: 字符的颜色
 * 			  bgColor
 * return：void
 */
void TFT_ST7735::drawHanZi1616(uint16_t x, uint16_t y, const char *hanZi,
							   uint16_t color, uint16_t bgColor)
{
	uint8_t i, j, m = 0, n = 0; // m记录行，n记录列
	uint16_t k;
	uint16_t HZnum;		  //汉字数目
	uint16_t TypefaceNum; //一个字符所占字节大小
	uint16_t x0 = x;
	uint8_t size = 16;
	TypefaceNum = (size / 8 + ((size % 8) ? 1 : 0)) * size;

	uint16_t localDisplayBuff[16 * 16] = {0}; // 先将底色绘制到内存中
	for (int i = 0; i < 16 * 16; i++)
	{
		localDisplayBuff[i] = bgColor;
	}

	HZnum = sizeof(tfont16) / sizeof(typFNT_GB16); //统计汉字数目
	for (k = 0; k < HZnum; k++)
	{
		if ((tfont16[k].Index[0] == *(hanZi)) && (tfont16[k].Index[1] == *(hanZi + 1)))
		{
			for (i = 0; i < TypefaceNum; i++)
			{
				for (j = 0; j < 8; j++)
				{
					if (tfont16[k].Msk[i] & (0x01 << j))
					{
						localDisplayBuff[n * 16 + m] = color;
					}
					m++; // 记录一行中的像素点位置
					if (m % size == 0)
					{
						n++;   // 一行记录完成，行号加一
						m = 0; // 列号清零
						break;
					}
				}
			}
		}
		continue; //查找到对应点阵字库立即退出，防止多个汉字重复取模带来影响
	}

	startWrite();
	if (setAddrWindow(x, y, size, size)) // 设置光标位置与填充区域
	{
		writePixels(localDisplayBuff, size * size);
	}
	endWrite();
}

/*
 * function:drawHanZi2424
 * parameter: x:x 轴显式坐标，
 *            y:y 轴显式坐标
 *			  hanZi:要显式中文
 *            color: 字符的颜色
 * 			  bgColor
 * return：void
 */
void TFT_ST7735::drawHanZi2424(uint16_t x, uint16_t y, const char *hanZi,
							   uint16_t color, uint16_t bgColor)
{
	uint8_t i, j, m = 0, n = 0; // m记录行，n记录列
	uint16_t k;
	uint16_t HZnum;		  //汉字数目
	uint16_t TypefaceNum; //一个字符所占字节大小
	uint16_t x0 = x;
	uint8_t size = 24;
	TypefaceNum = (size / 8 + ((size % 8) ? 1 : 0)) * size;

	uint16_t localDisplayBuff[24 * 24] = {0}; // 先将底色绘制到内存中
	for (int i = 0; i < 24 * 24; i++)
	{
		localDisplayBuff[i] = bgColor;
	}

	HZnum = sizeof(tfont24) / sizeof(typFNT_GB24); //统计汉字数目
	for (k = 0; k < HZnum; k++)
	{
		if ((tfont24[k].Index[0] == *(hanZi)) && (tfont24[k].Index[1] == *(hanZi + 1)))
		{
			for (i = 0; i < TypefaceNum; i++)
			{
				for (j = 0; j < 8; j++)
				{
					//非叠加方式
					if (tfont24[k].Msk[i] & (0x01 << j))
					{
						localDisplayBuff[n * 24 + m] = color;
					}
					m++; // 记录一行中的像素点位置
					if (m % size == 0)
					{
						n++;   // 一行记录完成，行号加一
						m = 0; // 列号清零
						break;
					}
				}
			}
		}
		continue; //查找到对应点阵字库立即退出，防止多个汉字重复取模带来影响
	}
	startWrite();
	if (setAddrWindow(x, y, size, size)) // 设置光标位置与填充区域
	{
		writePixels(localDisplayBuff, size * size);
	}
	endWrite();
}

/*
 * function:drawHanZi3232
 * parameter: x:x 轴显式坐标，
 *            y:y 轴显式坐标
 *			  hanZi:要显式中文
 *            color: 字符的颜色
 * 			  bgColor
 * return：void
 */
void TFT_ST7735::drawHanZi3232(uint16_t x, uint16_t y, const char *hanZi,
							   uint16_t color, uint16_t bgColor)
{
	uint8_t i, j, m = 0, n = 0; // m记录行，n记录列
	uint16_t k;
	uint16_t HZnum;		  //汉字数目
	uint16_t TypefaceNum; //一个字符所占字节大小
	uint16_t x0 = x;
	uint8_t size = 32;
	TypefaceNum = (size / 8 + ((size % 8) ? 1 : 0)) * size;

	uint16_t localDisplayBuff[32 * 32] = {0}; // 先将底色绘制到内存中
	for (int i = 0; i < 32 * 32; i++)
	{
		localDisplayBuff[i] = bgColor;
	}

	HZnum = sizeof(tfont32) / sizeof(typFNT_GB32); //统计汉字数目
	for (k = 0; k < HZnum; k++)
	{
		if ((tfont32[k].Index[0] == *(hanZi)) && (tfont32[k].Index[1] == *(hanZi + 1)))
		{
			for (i = 0; i < TypefaceNum; i++)
			{
				for (j = 0; j < 8; j++)
				{
					if (tfont32[k].Msk[i] & (0x01 << j))
					{
						localDisplayBuff[n * 32 + m] = color;
					}
					m++; // 记录一行中的像素点位置
					if (m % size == 0)
					{
						n++;   // 一行记录完成，行号加一
						m = 0; // 列号清零
						break;
					}
				}
			}
		}
		continue; //查找到对应点阵字库立即退出，防止多个汉字重复取模带来影响
	}

	startWrite();
	if (setAddrWindow(x, y, size, size)) // 设置光标位置与填充区域
	{
		writePixels(localDisplayBuff, size * size);
	}
	endWrite();
}

void TFT_ST7735::drawHanZi(uint16_t x, uint16_t y, const char *hanZi,
						   uint16_t color, uint16_t bgColor, uint8_t size)
{
	while (*hanZi != 0)
	{
		if (size == 12)
			drawHanZi1212(x, y, hanZi, color, bgColor);
		else if (size == 16)
			drawHanZi1616(x, y, hanZi, color, bgColor);
		else if (size == 24)
			drawHanZi2424(x, y, hanZi, color, bgColor);
		else if (size == 32)
			drawHanZi3232(x, y, hanZi, color, bgColor);
		else
			return;
		hanZi += 2;
		x += size;
	}
}

#endif
